/*
 * Famon (http://code.google.com/p/famon/)
 * Copyright (c) 2010 Carl Crous.
 *
 * This file is part of Famon.
 *
 * Famon is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Famon is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Famon.  If not, see <http://www.gnu.org/licenses/>.
 */

package za.org.foobar.famon.model;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.gwt.user.client.ui.HasName;
import za.org.foobar.famon.util.DB;
import za.org.foobar.famon.util.DBQuery;

import javax.jdo.annotations.*;
import java.util.ArrayList;
import java.util.List;

/**
 *
 */
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Application extends ModelObject implements HasName {
    private static final String DEFAULT_VERSION_NAME = "-";

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key id;

    @Persistent
    private String name;

    @Persistent(mappedBy = "application")
    @Order(extensions = @Extension(vendorName="datanucleus", key="list-ordering", value="name asc"))    
    private List<ApplicationInstance> instanceList;

    @Persistent(mappedBy = "application")
    @Order(extensions = @Extension(vendorName="datanucleus", key="list-ordering", value="userId asc"))
    private List<ApplicationUser> userList;

    @Persistent
    private boolean isPrivate;

    public Application() {
    }

    public Application(String name) {
        this.name = name;
    }

    public Key getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public DBQuery<ApplicationVersion> getVersionListQuery(boolean orderBy) {
        DBQuery<ApplicationVersion> q = DB.createDBQuery(ApplicationVersion.class)
                .addWhere("applicationId == applicationIdParam")
                .addParameter("applicationIdParam", id);
        if (orderBy) {
            q.addOrderBy("name asc");
        }
        return q;
    }

    public List<ApplicationVersion> getVersionList() {
        return getVersionListQuery(true).getResultList();
    }

    public DBQuery<ApplicationInstance> getInstanceListQuery(boolean orderBy) {
        DBQuery<ApplicationInstance> q = DB.createDBQuery(ApplicationInstance.class)
                .addWhere("applicationId == applicationIdParam")
                .addParameter("applicationIdParam", id);
        if (orderBy) {
            q.addOrderBy("name asc");
        }
        return q;
    }

    public List<ApplicationInstance> getInstanceList() {
        return instanceList;
    }

    public void setInstanceList(List<ApplicationInstance> instanceList) {
        this.instanceList = instanceList;
    }

    public ApplicationVersion getVersionByNameTx(String versionName) {
        DB.begin();
        try {
            return getVersionByName(versionName);
        } finally {
            DB.commit();
        }
    }
    public ApplicationVersion getVersionByName(String versionName) {
        if (versionName == null) {
            versionName = DEFAULT_VERSION_NAME;
        }
        List<ApplicationVersion> versionList = DB.createDBQuery(ApplicationVersion.class)
                    .addWhere("applicationId == applicationIdParam")
                    .addWhere("name == nameParam")
                    .addParameter("applicationIdParam", id)
                    .addParameter("nameParam", versionName)
                    .getResultList();
        if (versionList.size() > 0) {
            return versionList.get(0);
        }
        ApplicationVersion version = new ApplicationVersion(versionName);
        version.setApplicationId(id);
        DB.persist(version);
        return version;
    }

    public ApplicationInstance getInstanceByNameTx(String instanceName) {
        DB.begin();
        try {
            return getInstanceByName(instanceName);
        } finally {
            DB.commit();
        }
    }
    public ApplicationInstance getInstanceByName(String instanceName) {
        for (ApplicationInstance instance : instanceList) {
            if (instance.getName().equals(instanceName)) {
                return instance;
            }
        }
        ApplicationInstance instance = new ApplicationInstance(instanceName);
        instance.setApplication(this);
        DB.persist(this);
        DB.persist(instance);
        return instance;
    }

    public void addUser(UserData user, int role) {
        ApplicationUser appUser = new ApplicationUser(this, user.getId(), role);
        DB.persist(appUser);
    }

    public void addUser(ApplicationUser user) {
        if (userList == null) {
            userList = new ArrayList<ApplicationUser>();
        }
        userList.add(user);
    }

    public List<ApplicationUser> getUserList() {
        return userList;
    }

    public boolean isPrivate() {
        return isPrivate;
    }

    public void setPrivate(boolean aPrivate) {
        isPrivate = aPrivate;
    }

    @Override
    public String toString() {
        return id + " [" + name + "]";
    }

    public DBQuery<Failure> getFailureListQuery(boolean orderBy) {
         DBQuery<Failure> q = DB.createDBQuery(Failure.class)
                 .addWhere("applicationId == applicationIdParam")
                 .addParameter("applicationIdParam", id);
        if (orderBy) {
            q.addOrderBy("date desc");
        }
        return q;
    }

    public List<Failure> getFailureList() {
         return getFailureListQuery(true).getResultList();
    }

    public void delete() {
        //Delete all failures
        deleteAll(getFailureList());
//        getFailureListQuery(false).deletePersistentAll(id);
        //Delete all instances
        deleteAll(instanceList);
        //Delete all versions
        deleteAll(getVersionList());
//        getVersionListQuery(false).deletePersistentAll(id);
        //Delete self
        super.delete();                                  
    }

    public String keyToString() {
        return keyToString(id);
    }

    public static String keyToString(Key id) {
        return Long.toString(id.getId());
    }

    public static Key stringToKey(String id) {
        return KeyFactory.createKey(Application.class.getSimpleName(), Long.parseLong(id));
    }
}

